/**
 * 获取对象的类型名称
 *
 * 此函数用于确定给定对象的构造函数名称，从而识别其类型。
 * 对于null和undefined值有特殊处理。
 *
 * @param obj - 需要检查类型的对象
 * @returns 对象的类型名称字符串
 *
 * @example
 * type(123); // 返回 "Number"
 * type("hello"); // 返回 "String"
 * type([]); // 返回 "Array"
 * type({}); // 返回 "Object"
 * type(null); // 返回 "null"
 * type(undefined); // 返回 "null"
 * type(new Date()); // 返回 "Date"
 * type(/test/); // 返回 "RegExp"
 */
export function type(obj: any) {
  if (!obj) {
    if (obj !== 0) {
      return 'null'
    }
  }
  return obj.constructor.name
}

/**
 * 修剪数组开头和结尾的空元素
 *
 * @param list - 需要修剪的数组
 * @returns 修剪后的数组（移除了开头和结尾的空元素）
 */
export function trim_na_element(list: any[]) {
  // 创建一个新数组来存储结果
  const result = [...list]

  // 从开头移除空元素
  while (result.length > 0) {
    const firstElement = result[0]
    if (firstElement === null || firstElement === undefined) {
      result.shift()
    } else if (String(firstElement).trim() === '') {
      result.shift()
    } else {
      break
    }
  }

  // 从结尾移除空元素
  while (result.length > 0) {
    const lastElement = result[result.length - 1]
    if (lastElement === null || lastElement === undefined) {
      result.pop()
    } else if (String(lastElement).trim() === '') {
      result.pop()
    } else {
      break
    }
  }

  return result
}

/**
 * 类似于Python的split函数，但增加了对分割结果数量的限制
 * 当指定num参数时，分割后的数组长度将被限制为num，多余的元素会被合并到最后一项中
 *
 * @param string - 需要分割的字符串
 * @param sep - 分割符
 * @param num - 限制分割后的数组长度，如果分割结果超过该数量，则将多余的元素合并到最后一项
 * @returns 分割后的字符串数组
 *
 * @example
 * // 基本用法
 * split("a,b,c,d,e", ",", 3);
 * // 返回 ["a", "b", "c,d,e"]
 *
 * // 不限制数量的分割
 * split("a,b,c,d,e", ",", 10);
 * // 返回 ["a", "b", "c", "d", "e"]
 *
 * // 使用空格分割
 * split("hello world test example", " ", 2);
 * // 返回 ["hello", "world test example"]
 */
export function split(string: string, sep: string, num: number) {
  /**
   * 类似于python的split函数，第三个参数num限定了分割后数组的长度，行为和js的split函数不同
   */
  let list = string.split(sep)

  if (num < list.length) {
    let last = list[num - 1]
    for (let i = num; i < list.length; i++) {
      console.log(i)
      last = last + sep + list[i]
    }
    list[num - 1] = last
    return list.slice(0, num)
  } else {
    return list
  }
}

/**
 * 计算字符串的显示长度，其中不同类型的字符具有不同的长度计算方式
 * - ASCII字符（半角字符）长度计为1
 * - 中文字符长度计为2
 * - 全角字符长度计为2
 *
 * @param str - 需要计算长度的字符串
 * @returns 字符串的实际显示长度
 *
 * @example
 * // 计算包含中英文的字符串长度
 * getStringLength("hello"); // 返回 5
 * getStringLength("你好"); // 返回 4
 * getStringLength("hello你好"); // 返回 9
 * getStringLength("hello world!"); // 返回 12
 * getStringLength("你好，世界！"); // 返回 12
 * getStringLength("hello你好world世界"); // 返回 18
 */
function getStringLength(str: string) {

  let totalLength = 0

  const list = String(str).split('')
  for (let i = 0; i < list.length; i++) {
    const s = list[i]
    if (s.match(/[\u0000-\u00ff]/g)) { //半角
      totalLength += 1
    } else if (s.match(/[\u4e00-\u9fa5]/g)) { //中文
      totalLength += 2
    } else if (s.match(/[\uff00-\uffff]/g)) { //全角
      totalLength += 2
    }
  }
  return totalLength
}

/**
 * Series 类似于一维数组或列表，是 pandas 中的基本数据结构之一。
 * 它包含数据值和对应的索引，并支持多种数据操作方法。
 *
 * @example
 * // 创建一个简单的 Series
 * const series1 = new Series([1, 2, 3, 4, 5]);
 *
 * // 创建带自定义索引的 Series
 * const series2 = new Series([10, 20, 30], ['a', 'b', 'c']);
 *
 * // 创建带名称的 Series
 * const series3 = new Series([100, 200, 300], ['x', 'y', 'z'], 'my_series');
 */
export class Series {
  data: any[]
  index: any[]
  name: any  // 添加name属性

  constructor(data: any[], index?: any[], name?: any) {  // 添加name参数
    this.data = data
    this.index = index || Array.from({ length: data.length }, (_, i) => i)
    this.name = name  // 初始化name属性

    if (this.data.length !== this.index.length) {
      throw new Error('Data and index must have the same length')
    }
  }

  // 添加str属性，返回一个字符串方法访问器
  get str(): StringMethods {
    return new StringMethods(this)
  }

  // 获取元素数量
  get length(): number {
    return this.data.length
  }

  // 获取值
  get(index: any): any {
    const idx = this.index.indexOf(index)
    if (idx === -1) {
      return undefined
    }
    return this.data[idx]
  }

  // 设置值
  set(index: any, value: any): void {
    const idx = this.index.indexOf(index)
    if (idx === -1) {
      // 如果索引不存在，则添加新元素
      this.index.push(index)
      this.data.push(value)
    } else {
      this.data[idx] = value
    }
  }

  // 获取指定索引的元素
  loc(index: any): any {
    return this.get(index)
  }

  getValueByName(name: string) {
    return this.loc(name)
  }

  // 通过位置获取元素
  iloc(position: number): any {
    if (position < 0 || position >= this.data.length) {
      return undefined
    }
    return this.data[position]
  }

  getValueByIndex(index: number) {
    return this.iloc(index)
  }

  // 创建一个支持方括号访问的代理对象
  get iloc_proxy(): any {
    const self = this
    if (typeof Proxy === 'undefined') {
      // 如果不支持Proxy，返回一个替代对象
      return {
        get: (pos: number) => self.iloc(pos)
      }
    }

    return new Proxy({}, {
      get(target: any, prop: any) {
        if (typeof prop === 'string' && /^\d+$/.test(prop)) {
          const position = parseInt(prop, 10)
          return self.iloc(position)
        }
        return undefined
      }
    })
  }

  // 显示前n个元素
  head(n: number = 5): Series {
    const endIndex = Math.min(n, this.data.length)
    return new Series(
      this.data.slice(0, endIndex),
      this.index.slice(0, endIndex),
      this.name  // 传递name参数
    )
  }

  // 显示后n个元素
  tail(n: number = 5): Series {
    const startIndex = Math.max(0, this.data.length - n)
    return new Series(
      this.data.slice(startIndex),
      this.index.slice(startIndex),
      this.name  // 传递name参数
    )
  }

  // 过滤数据
  filter(callback: (value: any, index: any, series: Series) => boolean): Series {
    const filteredData: any[] = []
    const filteredIndex: any[] = []

    for (let i = 0; i < this.data.length; i++) {
      if (callback(this.data[i], this.index[i], this)) {
        filteredData.push(this.data[i])
        filteredIndex.push(this.index[i])
      }
    }

    return new Series(filteredData, filteredIndex, this.name)  // 传递name参数
  }

  // 添加根据布尔Series过滤的方法
  filterByBoolean(booleanSeries: Series): Series {
    if (this.length !== booleanSeries.length) {
      throw new Error('Series lengths must match for boolean indexing')
    }

    const filteredData: any[] = []
    const filteredIndex: any[] = []

    for (let i = 0; i < this.length; i++) {
      if (booleanSeries.data[i] === true) {
        filteredData.push(this.data[i])
        filteredIndex.push(this.index[i])
      }
    }

    return new Series(filteredData, filteredIndex, this.name)
  }

  // 映射数据
  map(callback: (value: any, index: any, series: Series) => any): Series {
    const mappedData = this.data.map((value, i) => callback(value, this.index[i], this))
    return new Series(mappedData, [...this.index], this.name)  // 传递name参数
  }

  // 计算总和
  sum(): number {

    return this.as_number().reduce((acc, val) => acc + (typeof val === 'number' ? val : 0), 0)
  }

  // 计算平均值
  mean(): number {
    const numericData = this.as_number()
    return numericData.length > 0 ? this.sum() / numericData.length : 0
  }

  // 获取唯一值
  unique(): any[] {
    return [...new Set(this.data)]
  }

  as_number(): number[] {
    return this.data
      .map(val => {
        // 尝试将值转换为数字
        const num = Number(val)
        // 只有当转换结果是有效数字时才返回
        return isNaN(num) ? null : num
      })
      .filter(val => val !== null) as number[]
  }

// 计算最小值
  min(): number | undefined {
    const numericData = this.as_number()

    if (numericData.length === 0) {
      return undefined
    }
    return Math.min(...numericData)
  }

  // 计算最大值
  max(): number | undefined {
    const numericData = this.as_number()

    if (numericData.length === 0) {
      return undefined
    }
    return Math.max(...numericData)
  }

  // 检查是否包含某个值
  contains(value: any): boolean {
    return this.data.includes(value)
  }

  // 转换为数组
  toArray(): any[] {
    return [...this.data]
  }

  // 转换为对象
  toObject(): { [key: string]: any } {
    const obj: { [key: string]: any } = {}
    for (let i = 0; i < this.index.length; i++) {
      obj[this.index[i]] = this.data[i]
    }
    return obj
  }

  // 打印数据
  toString(): string {
    let result = 'Series:\n'
    if (this.name !== undefined) {
      result = `Series (name: ${this.name}):\n`
    }
    for (let i = 0; i < this.data.length; i++) {
      result += `${this.index[i]}: ${this.data[i]}\n`
    }
    return result
  }

  print() {
    console.log(this.toString())
  }
}

// DataFrame类 - 二维表格结构
export class DataFrame {
  data: { [key: string]: Series }
  columns: string[]
  index: any[]

  constructor(data: any, index?: any[], columns?: string[]) {
    this.data = {}
    this.columns = []
    this.index = []

    // 处理不同类型的输入数据
    if (Array.isArray(data)) {
      // 如果数据是数组
      if (data.length === 0) {
        this.columns = columns || []
        this.index = index || []
        return
      }

      // 检查是否是数组的数组（行数据）
      if (Array.isArray(data[0])) {
        // console.log(data[0])
        // 处理行数据
        this.columns = columns || Array.from({ length: data[0].length }, (_, i) => i.toString())
        this.index = index || Array.from({ length: data.length }, (_, i) => i)
        // console.log(this.columns)
        // console.log(this.index)
        for (let i = 0; i < this.columns.length; i++) {
          const columnData = data.map(row => row[i])
          this.data[this.columns[i]] = new Series(columnData, this.index)
        }
        // console.log(this.data)
      } else {
        // 处理对象数组
        this.index = index || Array.from({ length: data.length }, (_, i) => i)
        this.columns = columns || Object.keys(data[0])

        for (const column of this.columns) {
          const columnData = data.map((row: any) => row[column])
          this.data[column] = new Series(columnData, this.index)
        }
      }
    } else if (data instanceof Object) {
      // 如果数据是对象
      this.columns = columns || Object.keys(data)

      // 如果提供了index，则使用提供的index，否则尝试从数据中获取index
      if (index) {
        this.index = index
      } else {
        const firstSeries = Object.values(data)[0]
        if (firstSeries instanceof Series) {
          this.index = [...firstSeries.index]
        } else {
          // 如果没有Series对象，默认创建基于数据长度的索引
          const dataValues = Object.values(data)
          const dataLength = dataValues.length > 0 ?
            (Array.isArray(dataValues[0]) ? dataValues[0].length : 0) : 0
          this.index = Array.from({ length: dataLength }, (_, i) => i)
        }
      }

      for (const key of this.columns) {
        const series = data[key]
        if (series instanceof Series) {
          this.data[key] = series
        } else {
          this.data[key] = new Series(series as any[], this.index)
        }
      }
    }
  }

  /**
   * 返回一个迭代器，每次迭代返回一个包含索引和行数据的数组。
   * @returns 一个迭代器，每次迭代返回 [index, row] 的形式。
   */
  iterrows(): IterableIterator<[any, any[]]> {
    const self = this
    let index = 0

    // 创建一个迭代器函数
    function* iterator(): IterableIterator<[any, any[]]> {
      while (index < self.index.length) {
        const idx = self.index[index]
        const row = self.columns.map(col => self.data[col].iloc(index))
        yield [idx, row]
        index++
      }
    }

    return iterator()
  }

  // 获取行数
  get shape(): [number, number] {
    const rows = this.index.length
    const cols = this.columns.length
    return [rows, cols]
  }

  // 根据名称获取索引号，axis=0表示行索引，axis=1表示列索引
  getIndexByName(name: any, axis: number = 0): number {
    if (axis === 0) {
      // 获取行索引
      return this.index.indexOf(name)
    } else if (axis === 1) {
      // 获取列索引
      return this.columns.indexOf(name)
    } else {
      throw new Error('axis must be 0 (for rows) or 1 (for columns)')
    }
  }

  // 根据行标签获取整行数据作为Series
  getRowByTitle(label: any): Series | undefined {
    const rowIndex = this.index.indexOf(label)
    if (rowIndex === -1) {
      return undefined // 行标签不存在
    }

    // 创建包含整行数据的数组
    const rowData: any[] = []
    const rowIndices: any[] = []

    // 遍历所有列，获取该行的数据
    for (const column of this.columns) {
      rowData.push(this.data[column].iloc(rowIndex))
      rowIndices.push(column)
    }

    // 返回一个新的Series，其中数据是行的值，索引是列名
    return new Series(rowData, rowIndices)
  }

  getColumnByTitle(title: string): Series {
    // 获取列索引
    return this.proxy['title']
  }

  getSeriesByIndex(index: number, axis = 0) {
    console.log(`请使用 iloc(index)或iloc(":", index)方法代替getSeriesByIndex方法`)
  }

  // 获取列
  get(column: string): Series {
    return this.data[column]
  }

  // 获取指定行列的值
  loc(row: any, column: string): any {
    const series = this.data[column]
    if (!series) {
      return undefined
    }
    return series.get(row)
  }

  // 通过位置获取值
// 通过位置获取值
// 通过位置获取值
  iloc(row: number): Series;
  iloc(row: number, col: number): any;
  iloc(row: ':', col: number): Series; // 添加对整列访问的支持
  iloc(row: number | ':', col?: number): any {
    // 如果第一个参数是":"，表示选择整列
    if (row === ':') {
      if (col === undefined) {
        return undefined
      }

      if (col < 0 || col >= this.columns.length) {
        return undefined
      }

      const columnName = this.columns[col]
      return this.data[columnName]
    }

    // 原有逻辑保持不变
    if (row < 0 || row >= this.index.length) {
      return undefined
    }

    // 如果只传入一个参数，返回整行数据作为Series
    if (col === undefined) {
      const rowData: any[] = []
      const rowIndex: any[] = []

      for (let i = 0; i < this.columns.length; i++) {
        const column = this.columns[i]
        rowData.push(this.data[column].iloc(row))
        rowIndex.push(column)
      }

      return new Series(rowData, rowIndex)
    }

    // 如果传入两个参数，返回单个值
    if (col < 0 || col >= this.columns.length) {
      return undefined
    }
    const columnName = this.columns[col]
    return this.data[columnName].iloc(row)
  }

  // 创建一个支持方括号访问的代理对象
  get iloc_proxy(): any {
    const self = this
    if (typeof Proxy === 'undefined') {
      // 如果不支持Proxy，返回一个替代对象
      return {
        get: (row: number | ':', col?: number) => {
          if (row === ':') {
            if (col === undefined) {
              return undefined
            }

            if (col < 0 || col >= self.columns.length) {
              return undefined
            }

            return self.data[self.columns[col]]
          }

          if (col === undefined) {
            // 只提供行索引，返回整行数据
            if (row < 0 || row >= self.index.length) {
              return undefined
            }

            const rowData: any[] = []
            const rowIndex: any[] = []

            for (let i = 0; i < self.columns.length; i++) {
              const column = self.columns[i]
              rowData.push(self.data[column].iloc(row))
              rowIndex.push(column)
            }

            return new Series(rowData, rowIndex)
          }
          // 提供行列索引，返回单个值
          return self.iloc(row, col)
        }
      }
    }

    return new Proxy({}, {
      get(target: any, prop: any) {
        // 处理 df.iloc_proxy[":", col] 语法
        if (typeof prop === 'string' && prop.includes(',')) {
          const indices = prop.split(',').map(s => s.trim())
          if (indices.length === 2) {
            let rowIndex: number | ':' = NaN
            if (indices[0] === ':') {
              rowIndex = ':'
            } else {
              rowIndex = parseInt(indices[0], 10)
            }
            const colIndex = parseInt(indices[1], 10)
            if ((rowIndex === ':' || !isNaN(rowIndex)) && !isNaN(colIndex)) {
              // 使用类型断言确保参数类型匹配
              return self.iloc(rowIndex as number, colIndex)
            }
          }
          return undefined
        }

        // 处理 df.iloc_proxy[row] 语法
        if (typeof prop === 'string' && /^\d+$/.test(prop)) {
          const rowIndex = parseInt(prop, 10)

          // 对于单个索引，返回整行数据
          if (rowIndex >= 0 && rowIndex < self.index.length) {
            const rowData: any[] = []
            const rowIndices: any[] = []

            for (let i = 0; i < self.columns.length; i++) {
              const column = self.columns[i]
              rowData.push(self.data[column].iloc(rowIndex))
              rowIndices.push(column)
            }

            return new Series(rowData, rowIndices)
          }
          return undefined
        }

        // 处理 df.iloc_proxy[":"] 语法
        if (prop === ':') {
          // 返回一个代理对象，可以用于访问整列
          return new Proxy({}, {
            get(innerTarget: any, innerProp: any) {
              if (typeof innerProp === 'string' && /^\d+$/.test(innerProp)) {
                const colIndex = parseInt(innerProp, 10)
                return self.iloc(':', colIndex)
              }
              return undefined
            }
          })
        }

        // 处理嵌套访问 df.iloc_proxy[row][col]
        if (typeof prop === 'string' && /^\d+$/.test(prop)) {
          const rowIndex = parseInt(prop, 10)

          // 返回一个内部代理，用于处理列索引
          return new Proxy({}, {
            get(innerTarget: any, innerProp: any) {
              if (typeof innerProp === 'string' && /^\d+$/.test(innerProp)) {
                const colIndex = parseInt(innerProp, 10)
                return self.iloc(rowIndex, colIndex)
              }
              return undefined
            }
          })
        }
        return undefined
      }
    })
  }

// 创建支持方括号语法访问列的代理对象
  get proxy(): any {
    const self = this
    if (typeof Proxy === 'undefined') {
      // 如果不支持Proxy，返回一个替代对象，只支持get方法
      return {
        get: (column: string) => self.get(column)
      }
    }

    // 使用Proxy拦截属性访问
    return new Proxy({}, {
      get(target: any, prop: any) {
        // 如果是字符串属性（列名），返回对应的Series
        if (typeof prop === 'string') {
          // 检查是否存在该列
          if (self.columns.includes(prop)) {
            return self.get(prop)
          }
          // 对于特殊属性，返回DataFrame自身的属性
          if (prop === 'shape') {
            return self.shape
          }
          if (prop === 'columns') {
            return self.columns
          }
          if (prop === 'index') {
            return self.index
          }
        }
        // 对于其他情况，返回DataFrame自身的属性或方法
        return (self as any)[prop]
      }
    })
  }

  // 选择多列
  select(columns: string[]): DataFrame {
    const selectedData: { [key: string]: Series } = {}
    for (const column of columns) {
      if (this.data[column]) {
        selectedData[column] = this.data[column]
      }
    }
    const newDataFrame = new DataFrame({})
    newDataFrame.data = selectedData
    newDataFrame.columns = columns.filter(col => this.data[col])
    newDataFrame.index = [...this.index]
    return newDataFrame
  }

  // 根据条件过滤行
  filter(callback: (row: { [key: string]: any }, index: any) => boolean): DataFrame {
    const filteredIndex: any[] = []

    for (let i = 0; i < this.index.length; i++) {
      const row: { [key: string]: any } = {}
      const rowIndex = this.index[i]

      for (const column of this.columns) {
        row[column] = this.data[column].iloc(i)
      }

      if (callback(row, rowIndex)) {
        filteredIndex.push(rowIndex)
      }
    }

    // 构建新的DataFrame
    const filteredData: { [key: string]: Series } = {}
    for (const column of this.columns) {
      const series = this.data[column]
      const filteredSeriesData = filteredIndex.map(idx => series.get(idx))
      filteredData[column] = new Series(filteredSeriesData, filteredIndex)
    }

    const newDataFrame = new DataFrame({})
    newDataFrame.data = filteredData
    newDataFrame.columns = [...this.columns]
    newDataFrame.index = filteredIndex
    return newDataFrame
  }

  // 添加新列
  addColumn(name: string, data: any[] | Series): void {
    if (this.index.length === 0) {
      // 如果DataFrame为空
      const series = Array.isArray(data) ? new Series(data) : data
      this.data[name] = series
      this.columns.push(name)
      this.index = [...series.index]

      // 更新其他列以匹配新索引
      for (const column of this.columns) {
        if (column !== name) {
          this.data[column] = new Series([], this.index)
        }
      }
    } else {
      // 如果DataFrame不为空
      if (Array.isArray(data)) {
        if (data.length !== this.index.length) {
          throw new Error('Data length must match DataFrame row count')
        }
        this.data[name] = new Series(data, this.index)
      } else if (data instanceof Series) {
        if (data.length !== this.index.length) {
          throw new Error('Series length must match DataFrame row count')
        }
        this.data[name] = data
      }
      this.columns.push(name)
    }
  }

  dropByIndex(index: number) {
    return this.drop(this.index[index])
  }

  // 删除列
  /**
   * 从DataFrame中删除指定的行或列
   *
   * @param labels - 要删除的行索引或列名，可以是单个标签或标签数组
   * @param axis - 指定删除行还是列，0 或 'index' 表示删除行，1 或 'columns' 表示删除列
   * @returns 返回一个新的DataFrame，不包含指定的行或列
   *
   * @example
   * // 创建一个示例DataFrame
   * const df = new DataFrame({
   *   'A': [1, 2, 3],
   *   'B': [4, 5, 6],
   *   'C': [7, 8, 9]
   * }, [0, 1, 2]);
   *
   * // 删除列（axis=1 或 axis='columns'）
   * const dfWithoutB = df.drop('B', 1);
   * const dfWithoutAC = df.drop(['A', 'C'], 'columns');
   *
   * // 删除行（axis=0 或 axis='index'，这是默认值）
   * const dfWithoutRow1 = df.drop(1, 0);
   * const dfWithoutRow02 = df.drop([0, 2], 'index');
   */
  drop(labels: string | number | (string | number)[] = [], axis: number | string = 0): DataFrame {
    // 标准化 axis 参数
    let axisValue: number
    if (axis === 0 || axis === 'index') {
      axisValue = 0
    } else if (axis === 1 || axis === 'columns') {
      axisValue = 1
    } else {
      throw new Error('axis must be 0, 1, \'index\' or \'columns\'')
    }

    // 标准化 labels 参数为数组
    const labelsArray = Array.isArray(labels) ? labels : [labels]

    if (axisValue === 0) {
      // 删除行
      const newIndex = this.index.filter(idx => !labelsArray.includes(idx))
      const newData: { [key: string]: Series } = {}

      for (const column of this.columns) {
        const series = this.data[column]
        const filteredSeriesData = newIndex.map(idx => series.get(idx))
        newData[column] = new Series(filteredSeriesData, newIndex)
      }

      const newDataFrame = new DataFrame({})
      newDataFrame.data = newData
      newDataFrame.columns = [...this.columns]
      newDataFrame.index = newIndex
      return newDataFrame
    } else {
      // 删除列 (axisValue === 1)
      const newColumns = this.columns.filter(col => !labelsArray.includes(col))
      const newData: { [key: string]: Series } = {}

      for (const column of newColumns) {
        newData[column] = this.data[column]
      }

      const newDataFrame = new DataFrame({})
      newDataFrame.data = newData
      newDataFrame.columns = newColumns
      newDataFrame.index = [...this.index]
      return newDataFrame
    }
  }

  /**
   * 为DataFrame的指定轴分配新的索引标签
   *
   * @param labels - 新的索引标签列表或Series
   * @param axis - 指定要更新的轴，0 或 'index' 表示行索引，1 或 'columns' 表示列索引
   * @returns 返回一个新的DataFrame，具有更新后的索引标签
   *
   * @example
   * // 创建一个示例DataFrame
   * const df = new DataFrame({
   *   'A': [1, 2, 3],
   *   'B': [4, 5, 6]
   * });
   *
   * // 更改行索引标签
   * const dfWithNewIndex = df.set_axis(['a', 'b', 'c'], 0);
   * const dfWithNewIndex2 = df.set_axis(['a', 'b', 'c'], 'index');
   *
   * // 更改列索引标签
   * const dfWithNewColumns = df.set_axis(['I', 'II'], 1);
   * const dfWithNewColumns2 = df.set_axis(['I', 'II'], 'columns');
   *
   * // 使用Series作为标签
   * const seriesLabels = new Series(['x', 'y', 'z']);
   * const dfWithSeriesLabels = df.set_axis(seriesLabels, 0);
   */
  set_axis(labels: any[] | Series, axis: number | string = 0): DataFrame {
    // 标准化 axis 参数
    let axisValue: number
    if (axis === 0 || axis === 'index') {
      axisValue = 0
    } else if (axis === 1 || axis === 'columns') {
      axisValue = 1
    } else {
      throw new Error('axis must be 0, 1, \'index\' or \'columns\'')
    }

    // 处理 labels 参数，如果是 Series 类型则转换为数组
    let labelsArray: any[]
    if (labels instanceof Series) {
      labelsArray = labels.toArray()
    } else if (Array.isArray(labels)) {
      labelsArray = labels
    } else {
      throw new Error('labels must be an array or Series')
    }

    // 检查标签数量是否匹配
    if (axisValue === 0) {
      // 更改行索引
      if (labelsArray.length !== this.index.length) {
        throw new Error(`Length of new labels (${labelsArray.length}) does not match length of index (${this.index.length})`)
      }

      // 创建新的数据对象
      const newData: { [key: string]: Series } = {}
      for (const column of this.columns) {
        newData[column] = new Series([...this.data[column].data], labelsArray)
      }

      // 创建新的DataFrame
      const newDataFrame = new DataFrame({})
      newDataFrame.data = newData
      newDataFrame.columns = [...this.columns]
      newDataFrame.index = [...labelsArray]
      return newDataFrame
    } else {
      // 更改列索引
      if (labelsArray.length !== this.columns.length) {
        throw new Error(`Length of new labels (${labelsArray.length}) does not match number of columns (${this.columns.length})`)
      }

      // 创建新的数据对象
      const newData: { [key: string]: Series } = {}
      for (let i = 0; i < this.columns.length; i++) {
        const oldColumn = this.columns[i]
        const newColumn = labelsArray[i]
        newData[newColumn] = this.data[oldColumn]
      }

      // 创建新的DataFrame
      const newDataFrame = new DataFrame({})
      newDataFrame.data = newData
      newDataFrame.columns = [...labelsArray]
      newDataFrame.index = [...this.index]
      return newDataFrame
    }
  }

  // 设置索引
  /**
   * 使用现有列设置DataFrame索引（行标签）
   *
   * @param keys - 用作新索引的列名或列名数组
   * @param drop - 是否删除用作新索引的列，默认为true
   * @param append - 是否将列追加到现有索引，默认为false
   * @returns 返回一个新的DataFrame，具有更新后的索引
   *
   * @example
   * // 创建一个示例DataFrame
   * const df = new DataFrame({
   *   'month': [1, 4, 7, 10],
   *   'year': [2012, 2014, 2013, 2014],
   *   'sale': [55, 40, 84, 31]
   * });
   *
   * // 将'month'列设为索引
   * const dfWithMonthIndex = df.set_index('month');
   *
   * // 将'year'和'month'列设为多级索引
   * const dfWithMultiIndex = df.set_index(['year', 'month']);
   *
   * // 将'month'列设为索引但保留在数据中
   * const dfWithMonthIndexKeep = df.set_index('month', true, false);
   *
   * // 将'year'列追加到现有索引
   * const dfWithAppendedIndex = df.set_index('year', true, true);
   */
  set_index(keys: string | string[], drop: boolean = true, append: boolean = false): DataFrame {
    // 标准化 keys 参数为数组
    const keysArray = Array.isArray(keys) ? keys : [keys]

    // 检查所有键是否存在于列中
    for (const key of keysArray) {
      if (!this.columns.includes(key)) {
        throw new Error(`Column '${key}' does not exist in DataFrame`)
      }
    }

    // 获取新索引数据
    let newIndex: any[] = []
    if (append) {
      // 如果是追加模式，则将新索引附加到现有索引之后
      newIndex = this.index.map((idx, i) => {
        const indexValues = keysArray.map(key => this.data[key].iloc(i))
        return [idx, ...indexValues]
      })
    } else {
      // 如果不是追加模式，则直接使用指定列的值作为新索引
      newIndex = Array.from({ length: this.index.length }, (_, i) => {
        if (keysArray.length === 1) {
          return this.data[keysArray[0]].iloc(i)
        } else {
          return keysArray.map(key => this.data[key].iloc(i))
        }
      })
    }

    // 创建新的数据对象
    const newData: { [key: string]: Series } = {}
    const newColumns = drop ? this.columns.filter(col => !keysArray.includes(col)) : [...this.columns]

    for (const column of newColumns) {
      newData[column] = new Series([...this.data[column].data], newIndex)
    }

    // 创建新的DataFrame
    const newDataFrame = new DataFrame({})
    newDataFrame.data = newData
    newDataFrame.columns = newColumns
    newDataFrame.index = newIndex
    return newDataFrame
  }

  // 删除包含缺失值的行或列
  dropna(axis: number | string, how: string, thresh: number | undefined, subset: string[] | undefined, inplace: true): undefined;
  dropna(axis: number | string, how: string, thresh: number | undefined, subset: string[] | undefined, inplace: false): DataFrame;
  dropna(axis: number | string, how: string, thresh: number | undefined, subset: string[] | undefined): DataFrame;
  dropna(axis: number | string, how: string, thresh?: number): DataFrame;
  dropna(axis: number | string, how?: string): DataFrame;
  dropna(axis?: number | string): DataFrame;
  dropna(): DataFrame;
  dropna(axis: number | string = 0, how: string = 'any', thresh?: number, subset?: string[], inplace: boolean = false): DataFrame | undefined {
    // 参数标准化
    let axisValue: number
    if (axis === 'index' || axis === 0) {
      axisValue = 0
    } else if (axis === 'columns' || axis === 1) {
      axisValue = 1
    } else {
      throw new Error('axis must be 0, 1, \'index\' or \'columns\'')
    }

    // 如果是列操作
    if (axisValue === 1) {
      const columnsToDrop: string[] = []

      for (const column of this.columns) {
        const series = this.data[column]
        let naCount = 0
        let nonNaCount = 0

        // 计算缺失值和非缺失值的数量
        for (let i = 0; i < series.data.length; i++) {
          const value = series.data[i]
          if (value === null || value === undefined || (typeof value === 'number' && isNaN(value))) {
            naCount++
          } else {
            nonNaCount++
          }
        }

        // 根据参数决定是否删除列
        let shouldDrop = false
        if (thresh !== undefined) {
          shouldDrop = nonNaCount < thresh
        } else if (how === 'any') {
          shouldDrop = naCount > 0
        } else if (how === 'all') {
          shouldDrop = naCount === series.data.length
        }

        if (shouldDrop) {
          columnsToDrop.push(column)
        }
      }

      if (inplace) {
        columnsToDrop.forEach(col => {
          const colIndex = this.columns.indexOf(col)
          if (colIndex !== -1) {
            this.columns.splice(colIndex, 1)
            delete this.data[col]
          }
        })
        return undefined
      } else {
        return this.drop(columnsToDrop)
      }
    } else {
      // 行操作 (axisValue === 0)
      const filteredIndex: any[] = []

      for (let i = 0; i < this.index.length; i++) {
        const rowIndex = this.index[i]
        let naCount = 0
        let nonNaCount = 0

        // 确定要检查的列
        const columnsToCheck = subset && subset.length > 0 ? subset : this.columns

        // 计算缺失值和非缺失值的数量
        for (const column of columnsToCheck) {
          if (!this.data[column]) continue
          const series = this.data[column]
          const value = series.iloc(i)
          if (value === null || value === undefined || (typeof value === 'number' && isNaN(value))) {
            naCount++
          } else {
            nonNaCount++
          }
        }

        // 根据参数决定是否保留行
        let shouldKeep = true
        if (thresh !== undefined) {
          shouldKeep = nonNaCount >= thresh
        } else if (how === 'any') {
          shouldKeep = naCount === 0
        } else if (how === 'all') {
          shouldKeep = naCount < columnsToCheck.length
        }

        if (shouldKeep) {
          filteredIndex.push(rowIndex)
        }
      }

      // 构建新的DataFrame
      const filteredData: { [key: string]: Series } = {}
      for (const column of this.columns) {
        const series = this.data[column]
        const filteredSeriesData = filteredIndex.map(idx => series.get(idx))
        filteredData[column] = new Series(filteredSeriesData, filteredIndex)
      }

      if (inplace) {
        this.data = filteredData
        this.index = filteredIndex
        return undefined
      } else {
        const newDataFrame = new DataFrame({})
        newDataFrame.data = filteredData
        newDataFrame.columns = [...this.columns]
        newDataFrame.index = filteredIndex
        return newDataFrame
      }
    }
  }

  // 显示前n行
  head(n: number = 5): DataFrame {
    const headIndex = this.index.slice(0, Math.min(n, this.index.length))
    const headData: { [key: string]: Series } = {}

    for (const column of this.columns) {
      const series = this.data[column]
      const headSeriesData = headIndex.map(idx => series.get(idx))
      headData[column] = new Series(headSeriesData, headIndex)
    }

    const newDataFrame = new DataFrame({})
    newDataFrame.data = headData
    newDataFrame.columns = [...this.columns]
    newDataFrame.index = headIndex
    return newDataFrame
  }

  // 显示后n行
  tail(n: number = 5): DataFrame {
    const tailStartIndex = Math.max(0, this.index.length - n)
    const tailIndex = this.index.slice(tailStartIndex)
    const tailData: { [key: string]: Series } = {}

    for (const column of this.columns) {
      const series = this.data[column]
      const tailSeriesData = tailIndex.map(idx => series.get(idx))
      tailData[column] = new Series(tailSeriesData, tailIndex)
    }

    const newDataFrame = new DataFrame({})
    newDataFrame.data = tailData
    newDataFrame.columns = [...this.columns]
    newDataFrame.index = tailIndex
    return newDataFrame
  }

  // 根据列名排序
  sort(columns: string | string[], ascending: boolean = true): DataFrame {
    const sortColumns = Array.isArray(columns) ? columns : [columns]

    // 创建索引和数据的映射
    const indexWithData: { index: any; data: any }[] = this.index.map(idx => {
      const rowData: { [key: string]: any } = {}
      for (const column of this.columns) {
        rowData[column] = this.data[column].get(idx)
      }
      return { index: idx, data: rowData }
    })

    // 排序
    indexWithData.sort((a, b) => {
      for (const column of sortColumns) {
        const valA = a.data[column]
        const valB = b.data[column]

        if (valA < valB) {
          return ascending ? -1 : 1
        } else if (valA > valB) {
          return ascending ? 1 : -1
        }
      }
      return 0
    })

    const sortedIndex = indexWithData.map(item => item.index)
    const sortedData: { [key: string]: Series } = {}

    for (const column of this.columns) {
      const series = this.data[column]
      const sortedSeriesData = sortedIndex.map(idx => series.get(idx))
      sortedData[column] = new Series(sortedSeriesData, sortedIndex)
    }

    const newDataFrame = new DataFrame({})
    newDataFrame.data = sortedData
    newDataFrame.columns = [...this.columns]
    newDataFrame.index = sortedIndex
    return newDataFrame
  }

  // 在 DataFrame 类中添加转置属性
  get T(): DataFrame {
    return this.transpose()
  }

  /**
   * 转置DataFrame，行列互换
   * @returns 转置后的DataFrame
   */
  transpose(): DataFrame {
    // 如果是空的DataFrame，直接返回一个新的空DataFrame
    // console.log('转置前：', this.toString())
    if (this.index.length === 0 || this.columns.length === 0) {
      return new DataFrame([], [], [])
    }
    // console.log('转置')
    // 新的列是原来的行索引
    const newColumns = [...this.index]

    // 新的行索引是原来的列名
    const newIndex = [...this.columns]

    // 构建转置后的数据
    const newData: { [key: string]: Series } = {}

    // 对于每一个新列（原来行索引变成新列）
    for (let i = 0; i < newColumns.length; i++) {
      const newColumnName = newColumns[i]
      // console.log(i)
      // 构建这一列的数据（原来列变成新行）
      const rowData: any[] = []
      for (let j = 0; j < newIndex.length; j++) {
        const originalColumnName = newIndex[j]
        const originalSeries = this.data[originalColumnName]
        rowData.push(originalSeries.iloc(i))
      }
      // console.log(`新列 ${newColumnName}:`, rowData)

      // 创建新的Series
      newData[newColumnName] = new Series(rowData, newIndex)
    }

    // 创建并返回新的DataFrame
    const transposedDataFrame = new DataFrame({})
    transposedDataFrame.data = newData
    transposedDataFrame.columns = newColumns
    transposedDataFrame.index = newIndex
    // console.log('转置后：', transposedDataFrame.toString())
    return transposedDataFrame
  }

  // 分组操作
  groupBy(columns: string | string[]): GroupBy {
    return new GroupBy(this, Array.isArray(columns) ? columns : [columns])
  }

  // 显示基本信息
  info(): string {
    let info = `DataFrame: ${this.shape[0]} rows × ${this.shape[1]} columns\n`
    info += 'Columns:\n'
    for (const column of this.columns) {
      info += `  ${column}\n`
    }
    return info
  }

  // 打印数据
  toString(index: boolean = true): string {
    if (this.index.length === 0 || this.columns.length === 0) {
      return 'Empty DataFrame'
    }

    let indexWidth = 0
    if (index) {
      // 计算行索引列的最大宽度（考虑中文字符宽度）
      indexWidth = Math.max(...this.index.map(idx => getStringLength(String(idx))), getStringLength('Index'))
    }

    // 计算每列的最大宽度（考虑中文字符宽度）
    const colWidths: { [key: string]: number } = {}
    for (const column of this.columns) {
      const series = this.data[column]
      colWidths[column] = Math.max(
        getStringLength(column),
        ...series.data.map(val => getStringLength(String(val)))
      )
    }

    // 打印表头（包括行索引列的标题）
    let result = ''
    if (index) {
      // 计算需要的填充字符数
      const paddingNeeded = indexWidth - getStringLength('Index') + 2
      result += 'Index' + ' '.repeat(Math.max(0, paddingNeeded))
    }
    for (const column of this.columns) {
      // 计算需要的填充字符数
      const paddingNeeded = colWidths[column] - getStringLength(column) + 2
      result += column + ' '.repeat(Math.max(0, paddingNeeded))
    }
    result += '\n'

    // 打印分隔线
    if (index) {
      result += '-'.repeat(indexWidth) + '  '
    }
    for (const column of this.columns) {
      result += '-'.repeat(colWidths[column]) + '  '
    }
    result += '\n'

    // 打印数据（包括行索引）
    for (let i = 0; i < Math.min(this.index.length, 10); i++) {
      if (index) {
        const indexValue = String(this.index[i])
        // 计算需要的填充字符数
        const paddingNeeded = indexWidth - getStringLength(indexValue) + 2
        result += indexValue + ' '.repeat(Math.max(0, paddingNeeded))
      }
      for (const column of this.columns) {
        const value = String(this.data[column].iloc(i))
        // 计算需要的填充字符数
        const paddingNeeded = colWidths[column] - getStringLength(value) + 2
        result += value + ' '.repeat(Math.max(0, paddingNeeded))
      }
      result += '\n'
    }

    if (this.index.length > 10) {
      // 添加行索引列的空格占位
      if (index) {
        result += ' '.repeat(indexWidth + 2)
      }
      result += `... (${this.index.length - 10} more rows)\n`
    }

    return result
  }
}


// GroupBy类 - 分组操作
class GroupBy {
  df: DataFrame
  groupColumns: string[]

  constructor(df: DataFrame, groupColumns: string[]) {
    this.df = df
    this.groupColumns = groupColumns
  }

  // 聚合操作
  agg(func: 'sum' | 'mean' | 'count' | 'min' | 'max'): DataFrame {
    // 获取唯一分组
    const groups: { [key: string]: any[] } = {}

    for (let i = 0; i < this.df.index.length; i++) {
      const keyValues = this.groupColumns.map(col => this.df.data[col].iloc(i))
      const key = keyValues.join('|')

      if (!groups[key]) {
        groups[key] = []
      }
      groups[key].push(this.df.index[i])
    }

    // 构建结果DataFrame
    const resultIndex = Object.keys(groups)
    const resultData: { [key: string]: Series } = {}

    // 添加分组列
    for (const groupColumn of this.groupColumns) {
      const groupValues = Object.keys(groups).map(key => key.split('|')[this.groupColumns.indexOf(groupColumn)])
      resultData[groupColumn] = new Series(groupValues, resultIndex)
    }

    // 对其他列应用聚合函数
    const aggColumns = this.df.columns.filter(col => !this.groupColumns.includes(col))
    for (const column of aggColumns) {
      const aggValues: any[] = []

      for (const key of Object.keys(groups)) {
        const indices = groups[key]
        const series = this.df.data[column]
        const values = indices.map(idx => series.get(idx)).filter(val => typeof val === 'number')

        switch (func) {
          case 'sum':
            aggValues.push(values.reduce((a, b) => a + b, 0))
            break
          case 'mean':
            aggValues.push(values.length > 0 ? values.reduce((a, b) => a + b, 0) / values.length : 0)
            break
          case 'count':
            aggValues.push(indices.length)
            break
          case 'min':
            aggValues.push(values.length > 0 ? Math.min(...values) : undefined)
            break
          case 'max':
            aggValues.push(values.length > 0 ? Math.max(...values) : undefined)
            break
        }
      }

      resultData[column] = new Series(aggValues, resultIndex)
    }

    const newDataFrame = new DataFrame({})
    newDataFrame.data = resultData
    newDataFrame.columns = [...this.groupColumns, ...aggColumns]
    newDataFrame.index = resultIndex
    return newDataFrame
  }
}


// 创建辅助函数
export function read_csv(url: string): DataFrame {
  // 在实际实现中，这里会处理CSV文件
  // 目前返回一个空的DataFrame作为示例
  return new DataFrame([])
}

export function concat(dataFrames: DataFrame[]): DataFrame {
  if (dataFrames.length === 0) {
    return new DataFrame([])
  }

  if (dataFrames.length === 1) {
    return dataFrames[0]
  }

  // 检查所有DataFrame是否具有相同的列
  const firstColumns = dataFrames[0].columns
  for (let i = 1; i < dataFrames.length; i++) {
    if (JSON.stringify(dataFrames[i].columns) !== JSON.stringify(firstColumns)) {
      throw new Error('All DataFrames must have the same columns')
    }
  }

  // 合并数据
  const mergedData: { [key: string]: any[] } = {}
  const mergedIndex: any[] = []

  for (const column of firstColumns) {
    mergedData[column] = []
  }

  for (const df of dataFrames) {
    for (const column of firstColumns) {
      mergedData[column].push(...df.data[column].toArray())
    }
    mergedIndex.push(...df.index)
  }

  return new DataFrame(mergedData)
}

// 添加字符串方法类
export class StringMethods {
  series: Series

  constructor(series: Series) {
    this.series = series
  }

  // 实现endswith方法，返回一个过滤后的Series，只包含满足条件的元素
  endswith(suffix: string): Series {
    const filteredData: any[] = []
    const filteredIndex: any[] = []

    for (let i = 0; i < this.series.data.length; i++) {
      const item = this.series.data[i]
      if (item !== null && item !== undefined) {
        const str = String(item)
        if (str.endsWith(suffix)) {
          filteredData.push(item)
          filteredIndex.push(this.series.index[i])
        }
      }
    }

    return new Series(filteredData, filteredIndex)
  }

  // 实现startswith方法，返回一个过滤后的Series，只包含满足条件的元素
  startswith(prefix: string): Series {
    const filteredData: any[] = []
    const filteredIndex: any[] = []

    for (let i = 0; i < this.series.data.length; i++) {
      const item = this.series.data[i]
      if (item !== null && item !== undefined) {
        const str = String(item)
        if (str.startsWith(prefix)) {
          filteredData.push(item)
          filteredIndex.push(this.series.index[i])
        }
      }
    }

    return new Series(filteredData, filteredIndex)
  }

  // 实现contains方法，返回一个过滤后的Series，只包含满足条件的元素
  contains(substring: string): Series {
    const filteredData: any[] = []
    const filteredIndex: any[] = []

    for (let i = 0; i < this.series.data.length; i++) {
      const item = this.series.data[i]
      if (item !== null && item !== undefined) {
        const str = String(item)
        if (str.includes(substring)) {
          filteredData.push(item)
          filteredIndex.push(this.series.index[i])
        }
      }
    }

    return new Series(filteredData, filteredIndex)
  }

  // 实现lower方法
  lower(): Series {
    const resultData = this.series.data.map(item => {
      if (item === null || item === undefined) {
        return item
      }
      return String(item).toLowerCase()
    })
    return new Series(resultData, [...this.series.index])
  }

  // 实现upper方法
  upper(): Series {
    const resultData = this.series.data.map(item => {
      if (item === null || item === undefined) {
        return item
      }
      return String(item).toUpperCase()
    })
    return new Series(resultData, [...this.series.index])
  }

  // 实现strip方法
  strip(chars?: string): Series {
    const resultData = this.series.data.map(item => {
      if (item === null || item === undefined) {
        return item
      }
      const str = String(item)
      if (chars) {
        // 自定义字符去除
        let start = 0
        let end = str.length

        while (start < end && chars.includes(str[start])) {
          start++
        }

        while (end > start && chars.includes(str[end - 1])) {
          end--
        }

        return str.slice(start, end)
      } else {
        // 默认去除空白字符
        return str.trim()
      }
    })
    return new Series(resultData, [...this.series.index])
  }
}


// 导出类
export default {
  Series, DataFrame, GroupBy, type,
  split, getStringLength, concat, read_csv
}